package com.ymt.fmd.platform.formdesigner.parser;

import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Logger;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import com.alibaba.fastjson.JSONObject;
import com.ymt.fmd.appboot.prop.FmdProperties;
import com.ymt.fmd.util.ModuleUtil;

/**
 * Abstract class of parser
 */
public abstract class AbstractJsParser implements Parser {
	
	public static final String PARSER_JS_PARSER = "parser";
	public static final String PARSER_JS_PRINTER = "printer";
	protected static final String STATIC_PATH = "/static";

	protected ScriptEngine engine;//script engine
	protected String skin;//form skin
	protected String realPath;//real path
	protected String lang;//language
	protected String parserJsName = PARSER_JS_PARSER;
	//logger
	protected Logger logger = Logger.getLogger(AbstractJsParser.class.getName());

	protected FmdProperties fmdProperties;

	/**
	 * init the parser
	 * @param realPath
	 * @param skin
	 * @param lang
	 * @throws Exception
	 */
	@Override
	public void init(FmdProperties fmdProperties, String realPath, String skin, String lang, String parserJsName) throws Exception {
		this.skin = skin;
		this.realPath = realPath;
		this.lang = lang;
		this.fmdProperties = fmdProperties;
		if (parserJsName!=null && parserJsName.length()>0) {	//override parserJsName
			this.parserJsName = parserJsName;
		}
		String implShortName = this.getClass().getSimpleName();
		// engine manager
		ScriptEngineManager engineManager = new ScriptEngineManager();
		// 得到脚本引擎
		this.engine = engineManager.getEngineByName("JavaScript");
		//put logger
		engine.put("logger", logger);
		// 引入工具库
		/*engine.eval(new java.io.FileReader(
				realPath + STATIC_PATH + "/js/3rdpartyother/json2.js"));
		engine.eval(new java.io.FileReader(
				realPath + STATIC_PATH + "/js/3rdpartyother/json2html.js"));*/
		ModuleUtil.importFile(engine, new File(realPath + STATIC_PATH + "/js/3rdpartyother/json2.js"));
		ModuleUtil.importFile(engine, new File(realPath + STATIC_PATH + "/js/3rdpartyother/json2html.js"));
		ModuleUtil.importFile(engine, new File(realPath + STATIC_PATH + "/js/platform/form/formdesigner_elem_i18n_zh.js"));
		
		engine.eval("Parser = function() {};");
		engine.eval("Parser.log = function(msg) {logger.finer('[JS:"+implShortName+"]:'+(msg==null ? 'undefined' : msg.toString()));};");
		engine.eval("Parser.warning = function(msg) {logger.warning('[JS:"+implShortName+"]:'+(msg==null ? 'undefined' : msg.toString()));};");
		engine.eval("Parser.formskin='"+skin+"';");	//skin name
		engine.eval("Parser.lang='"+lang+"';");	//lang
		engine.eval("Parser.impl='"+implShortName+"';");	//impl
		engine.eval("Parser.fmdv = {};");	//variables auto generated by parser
		engine.eval("Parser.fmdv.dataprovider = {};");	//dataprovider that need to be further parsed, such as dictionary, rest service
		engine.eval("Parser.fmdv.ui = {};");	//contains some dynamic ui components on the page, such as dhxgrid, specified by id
		engine.eval("Parser.generatedscript = '';");	//script auto generated by parser
		engine.eval("Parser.log('Parser.formskin=='+Parser.formskin)");
		engine.eval("Parser.log('Parser.lang=='+Parser.lang)");
		engine.eval("Parser.log('Parser.impl=='+Parser.impl)");
		
		/*engine.eval(new java.io.FileReader(
				realPath + FmdSettings.getValue(FmdSettings.FMD_MODULE_PATH_BASE) + "/"+implShortName+".js"));*/
		ModuleUtil.importFile(engine, new File(
				realPath + this.fmdProperties.getModulesPathBase() + "/"+implShortName+".js"));
		
		//import modules
		importAllModules(engine);
	}
	
	/**
	 * get form js parser config by formtype
	 * @param formtype
	 * @return
	 * @throws ScriptException
	 */
	@Override
	public JSONObject getFormJsParserConfig(String formtype) throws ScriptException {
		String key = "form:"+formtype+":"+this.skin+":"+this.getClass().getSimpleName()+":parserconfig";
		logger.finer("getFormJsParserConfig finding key="+key);
		String cfgstr = (String)engine.eval("Parser['"+key+"'] ? JSON.stringify(Parser['"+key+"']) : ''");
		if (cfgstr==null || cfgstr.trim().length()==0) {
			return null;
		} else {
			return JSONObject.parseObject(cfgstr);
		}
	}
	
	/**
	 * import modules
	 * @param engine
	 * @throws FileNotFoundException
	 * @throws ScriptException
	 */
	private void importAllModules(ScriptEngine engine) throws IOException, ScriptException {
		File mFolder = new File(realPath +
				this.fmdProperties.getModulesPathBase());
		File[] types = mFolder.listFiles(new FileFilter(){
			@Override
			public boolean accept(File arg0) {
				return arg0.isDirectory();
			}
		});
		
		//prepare for importing i18n js
		engine.eval("if (typeof(fmd_i18n_modules)=='undefined') fmd_i18n_modules={};");
		
		for (File t : types) {
			String[] mns = t.list();
			for (String mn : mns) {
				logger.finer("importAllModules find module: "+t.getName()+"/"+mn);
				//import parser js
				File mnf = new File(realPath +
						this.fmdProperties.getModulesPathBase() + "/"+ t.getName()+"/"+mn+"/"+parserJsName+".js");
				if (mnf.exists()) {
					//engine.eval(new java.io.FileReader(mnf));
					ModuleUtil.importFile(engine, mnf);
				} else {
					//when parserJsName file doesn't exist and parserJsName!=parser, use default parser.js
					logger.finer("importAllModules did not find module custom parser js: "+t.getName()+"/"+mn+"/"+parserJsName+".js, using default parser js.");
					if (!PARSER_JS_PARSER.equalsIgnoreCase(parserJsName)) {
						mnf = new File(realPath +
								this.fmdProperties.getModulesPathBase() + "/"+ t.getName()+"/"+mn+"/"+PARSER_JS_PARSER+".js");
						if (mnf.exists()) {
							ModuleUtil.importFile(engine, mnf);
						}
					}
				}
				//import i18n js
				mnf = new File(realPath +
						this.fmdProperties.getModulesPathBase() + "/"+ t.getName()+"/"+mn+"/i18n_"+lang+".js");
				if (mnf.exists()) {
					ModuleUtil.importFile(engine, mnf);
				}
			}
		}
	}

}
